package com.cn.plugin.interceptor;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.PreparedStatement;
import java.util.List;
import java.util.Properties;

/**
 * 通过参数对象 ，参数设置
 *
 * @author : Hydra
 * @date: 2021/3/10 9:13
 * @version: 1.0
 */
@Intercepts({
        @Signature(type= ParameterHandler.class,method = "setParameters",args = {PreparedStatement.class})
})
public class ParameterPlugin implements Interceptor {

    //拦截目标方法执行
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("Parameter Plugin 拦截 :"+invocation.getMethod());
        ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();
        PreparedStatement ps = (PreparedStatement) invocation.getArgs()[0];

        // 获取 BoundSql 对象，此对象包含生成的sql和sql的参数map映射
        MetaObject metaObject = SystemMetaObject.forObject(parameterHandler);
        BoundSql boundSql = (BoundSql) metaObject.getValue("boundSql");

        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();


//        parameterHandler.setParameters(ps);
        return invocation.proceed();
    }

    //让mybatis判断，是否要进行拦截，然后做出决定是否生成一个代理
    //生成动态代理对象
    @Override
    public Object plugin(Object target) {
        // 当目标类是 ParameterHandler 类型时，才包装目标类，否则直接返回目标本身,减少目标被代理的次数
        if(target instanceof ParameterHandler)
            return Plugin.wrap(target, this);
        return target;
    }

    //注入插件配置时设置的属性
    @Override
    public void setProperties(Properties properties) {
    }

}
